import { endUnitReg, endWithRpxOrUpxReg, strToNumReg } from "@/utils/reg.js"; // 引入正则表达式

import colorInfo from "@/utils/color.js"; // 引入主题色配置

let loadingTimer = null; //加载中定时器
let loadingTimer2 = null; // 加载中定时器
let toastTimer = null; // 弹框定时器


/**
 * @description 获取节点信息
 * @param selector 节点选择器
 * @param self 如果是在组件内，需要传入this
 * @returns {Promise<unknown>}
 */
export function getRect(selector, self) {
    return new Promise((resolve) => {
        if (!self) {
            // console.log("获取页面节点信息");
            const query = uni.createSelectorQuery();
            query
                .select(selector)
                .boundingClientRect(resolve)
                .exec();
        } else {
            // console.log("获取组件节点信息");
            // 获取组件的节点布局信息
            const query = uni.createSelectorQuery().in(self);
            query
                .select(selector)
                .boundingClientRect(resolve)
                .exec();
        }
    });
}



/**
 * @description 去除字符串空格
 * @param str 字符串内容
 * @param pos 去除空格的方式
 * @returns {*}
 */
export function trim(str, pos = "both") {
    if (typeof str !== "string") return str;
    switch (pos) {
        // 去除两边空格
        case "both":
            return str.replace(/^\s+|\s+$/g, "");
        // 去除左边空格
        case "left":
            return str.replace(/^\s*/, "");
        // 去除右边空格
        case "right":
            return str.replace(/(\s*$)/g, "");
        // 去除所有空格
        case "all":
            return str.replace(/\s+/g, "");
        default:
            return str;
    }
}

/**
 * @description 显示loading加载中
 * @param title 标题
 * @param mask 是否开启禁止操作遮罩
 * @param loadingTime 加载时间
 */
export function showLoading(title, mask, loadingTime) {
    // 默认10秒关闭
    loadingTime = Number(loadingTime) >= 0 ? Number(loadingTime) : 10000;
    uni.showLoading({
        title: title || "正在加载中...",
        mask: mask !== false,
    });
    // 每次调用之前清除定时器
    loadingTimer && clearTimeout(loadingTimer);
    // 最长10s自动关闭
    loadingTimer = setTimeout(() => {
        uni.hideLoading();
    }, loadingTime);
}

/**
 * @description 隐藏loading
 * @param loadingTime 多少秒后隐藏loading
 * @param callback 关闭loading后的回调
 */
export function hideLoading(loadingTime, callback) {
    // 默认loading时间是300ms
    loadingTime = Number(loadingTime) >= 0 ? Number(loadingTime) : 300;
    if (loadingTime > 0) {
        // 每次调用之前清除定时器
        loadingTimer2 && clearTimeout(loadingTimer2);
        // 最短loadingTime加载时间
        loadingTimer2 = setTimeout(() => {
            uni.hideLoading();
            typeof callback === "function" && callback();
        }, loadingTime);
    } else {
        // 清除showLoading的定时器
        loadingTimer && clearTimeout(loadingTimer);
        uni.hideLoading();
    }
}

/**
 * @description 检测数据类型
 * @param target 检测的目标
 * @returns {string}
 */
export function checkType(target) {
    return Object.prototype.toString
        .call(target)
        .slice(8, -1)
        .toLowerCase();
}

/**
 * @description 动态添加单位
 * @param val 传过来的参数
 * @param unit 要拼接的单位
 * @returns {string}
 */
export function addUnit(val = "", unit = "rpx") {
    // 0的情况特殊处理下
    if (val === 0 || val === "0" || val === "0px") return "0px";
    // 如果属性不传值或者设置空字符串，会把属性值变成true，这里特殊处理下，返回auto。
    if (!val || val === true) return "auto";
    // 将数据类型转换成字符串类型，并去掉所有空格
    val = String(val).replace(/\s+/g, "");
    // 包含css计算属性的话，返回对应的字符串
    if (val.includes("calc(")) return val;
    // 提取所有数字部分，匹配到的话是个数组，匹配不到是null
    const matchList = val.match(strToNumReg);
    // console.log(matchList);
    // 匹配不到，或者包含auto，全部取auto
    if (!matchList || val.includes("auto")) return "auto";
    // 匹配到了就取数组最后一个
    const matchVal = matchList[matchList.length - 1];
    // 判断字符串是否以rpx、upx结尾，并拼接上rpx
    if (endWithRpxOrUpxReg.test(val)) {
        val = matchVal + "rpx";
    } else if (endUnitReg.test(val)) {
        // 判断字符串中是否以%、vw、vh、rem、em、px结尾，拼接上对应单位
        val = matchVal + val.match(endUnitReg)[0];
    } else {
        // 只有纯数字的情况下就拼接unit
        val = matchVal + unit;
    }
    // console.log(val);
    return val;
}

/**
 * @description 全局showToast
 * @param title 标题
 * @param showIcon 是否显示成功图标
 * @param callback 回调函数
 * @param mask 是否显示遮罩
 * @param duration 显示时长
 */
export function showToast(title, showIcon, callback, mask, duration) {
    duration = Number(duration) >= 0 ? Number(duration) : 1500; // 默认弹框时间1500ms
    uni.showToast({
        title: title || "",
        icon: !showIcon || (title && title.length > 7) ? "none" : "success",
        mask: mask !== false,
        duration: duration,
        complete: () => {
            // 判断callback是否是函数，如果不是函数就不执行
            if (checkType(callback) !== "function") return;
            // 每次调用之前清除定时器
            toastTimer && clearTimeout(toastTimer);
            // 延时回调
            toastTimer = setTimeout(() => {
                callback();
            }, duration);
        },
    });
}

/**
 * @description 全局showModal
 * @param content 模态框内容
 * @param title 模态框标题
 * @param cancelText 取消按钮文字
 * @param confirmText 确定按钮文字
 * @param confirmColor 确定按钮颜色
 * @param cancelColor 取消按钮颜色
 */
export function showModal(
    content,
    title,
    cancelText,
    confirmText,
    confirmColor,
    cancelColor
) {
    content = typeof content === "string" ? content : "";
    title = typeof title === "string" ? title : "温馨提示";
    // 取消文字特殊处理
    if (cancelText === undefined) {
        cancelText = "取消";
    } else if (!cancelText) {
        cancelText = "";
    } else {
        cancelText = typeof cancelText === "string" ? cancelText : "取消";
    }
    confirmText = typeof confirmText === "string" ? confirmText : "确定";
    confirmColor =
        typeof confirmColor === "string" ? confirmColor : colorInfo.themeColor;
    cancelColor =
        typeof cancelColor === "string" ? cancelColor : colorInfo.fontColor;
    return new Promise((resolve) => {
        uni.showModal({
            title: title,
            cancelText: cancelText,
            confirmText: confirmText,
            confirmColor: confirmColor,
            cancelColor: cancelColor,
            showCancel: cancelText.length > 0,
            content: content,
            success: (res) => {
                if (res.confirm) {
                    resolve(true);
                } else if (res.cancel) {
                    resolve(false);
                }
            },
            fail: (err) => {
                console.log("模态框异常", err);
            },
        });
    });
}

/**
 * @description 预览大图
 * @param {Object} urls 图片地址
 * @param {Object} current 图片索引
 */
export function previewImage(urls, current) {
    current = Number(current) >= 0 ? Number(current) : 0; // 默认当前索引是0，就是第1张
    // 传入的图片是数组就直接赋值
    if (checkType(urls) === "array" && urls.length > 0) {
        uni.previewImage({
            urls,
            current: current,
            fail: (err) => {
                showToast("预览图片失败");
                console.log("数组类型，预览图片失败", err);
            },
        });
    } else if (checkType(urls) === "string" && urls.length > 0) {
        // 传入的是字符串，就单张预览
        uni.previewImage({
            urls: [urls],
            current: current,
            fail: (err) => {
                showToast("预览图片失败");
                console.log("字符串类型，预览图片失败", err);
            },
        });
    } else {
        console.log("预览图片失败，数据格式不正确", urls);
    }
}

/**
 * @description 拨打电话
 * @param phoneNumber 电话号码
 */
export function makePhoneCall(phoneNumber) {
    // if (!phoneNumber) return showToast("拨打电话失败，电话号码不合法");
    // uni.makePhoneCall({
    // 	phoneNumber: phoneNumber + "",
    // 	success: () => {
    // 		console.log("拨打电话成功");
    // 	},
    // 	fail: (err) => {
    // 		if (err.errMsg.includes("cancel")) {
    // 			console.log("取消拨打电话");
    // 		} else {
    // 			showToast("拨打电话失败");
    // 			console.log(err);
    // 		}
    // 	},
    // });
}


/**
 * @description 比较版本号大小
 * @param {string} v1
 * @param {string} v2
 * @returns {number} 1：有新版本 -1:没有新版本 0：版本号一致
 */
export function compareVersion(v1, v2) {
    v1 = v1.split(".");
    v2 = v2.split(".");
    const len = Math.max(v1.length, v2.length);
    while (v1.length < len) {
        v1.push("0");
    }
    while (v2.length < len) {
        v2.push("0");
    }
    for (let i = 0; i < len; i++) {
        const num1 = parseInt(v1[i], 10);
        const num2 = parseInt(v2[i], 10);

        if (num1 > num2) {
            return 1;
        } else if (num1 < num2) {
            return -1;
        }
    }
    return 0;
}